home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
idle
/
idleout-.tar
/
idleout-mcm.tar
/
autologout.c
next >
Wrap
C/C++ Source or Header
|
1994-10-15
|
7KB
|
178 lines
/*
"@(#) autologout.c by David Dickson"
Modified by Michael C. Mitchell, 15Oct94
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utmp.h>
#define GRACE 60 /* grace time (sec) for user reply */
#define KWAIT 20 /* time to wait after kill (in sec.) */
#define WARNING 1 /* a warning message */
#define LOGOFF 2 /* a log-off message */
#define NOLOGOFF 3 /* a log-off failure message */
#define SEC 60 /* seconds per minute */
#define TIMEMAX 10 /* maximum idle time (minutes) */
struct utmp *utmpp; /* pointer to utmp file entry */
char *ctime(); /* returns pointer to time string */
struct utmp *getutent(); /* returns next utmp file entry */
main()
{
if (fork()) /* the parent process */
exit(0); /* exits */
/* the child processes all utmp file entries: */
while ((utmpp = getutent()) != (struct utmp *) NULL)
check_idle();
exit(0); /* done, so bye */
}
check_idle() /* select utmp entries older than TIMEMAX */
{
char dev[24], name[12];
struct stat status, *pstat;
time_t idle, pres_time, start, time();
FILE *in_file;
char in_name[8];
pstat = &status; /* point to status structure */
if (utmpp->ut_type != USER_PROCESS) /* if not user process */
return(0); /* skip the utmp entry */
strcpy(dev, "/dev/"); /* add "/dev/" directory prefix */
strcat(dev, utmpp->ut_line); /* append basename of port */
if (stat(dev, pstat)) /* if can't get status for port */
bailout("can't get status of user's terminal", 1);
pres_time = time((time_t *)0); /* get current time */
/* idle time is current time less last access time: */
idle = (pres_time - pstat->st_atime) / SEC;
if (idle < TIMEMAX) /* if user was recently active */
return(0); /* ignore this utmp entry */
strncpy(name, utmpp->ut_user, 8); /* else get user name */
name[8] = '\0'; /* null terminate user name string */
/* mcm 15Oct94 */
if ( (in_file=fopen("/etc/autologout.exempt", "r")) != NULL)
{
while (fscanf(in_file, "%s", in_name) != EOF)
{
if (!strcmp(name,in_name))
{
fclose(in_file);
return(0); /* user exempt */
}
}
fclose(in_file);
}
/* mcm 15Oct94 */
mesg(WARNING, name, dev, (int)idle); /* send warning to user */
if (stat(dev, pstat))
bailout("can't get status of user's terminal", 2);
start = pstat->st_atime; /* start time for countdown */
sleep(GRACE);
if (stat(dev, pstat))
bailout("can't get status of user's terminal", 3);
if (start < pstat->st_atime) /* user did something */
return(0);
else { /* user abandoned terminal */
if (!killit(utmpp->ut_pid))
mesg(NOLOGOFF, name, dev, (int)idle); /* couldn't kill */
else
mesg(LOGOFF, name, dev, (int)idle); /* okay */
return(0);
}
}
mesg(flag, name, dev, idle) /* mail to user and log message */
int flag, idle; /* flag indicates message type */
char *name, *dev;
{
char mbuf[256]; /* message buffer */
time_t tvec;
FILE *fopen(), *fp, *log, *mprog;
time(&tvec); /* store time in tvec */
if ((log = fopen("/usr/adm/logoutlog", "a")) == (FILE *) NULL)
bailout("can't open log file", 4);
if (flag == WARNING) { /* process warning message */
if ((fp = fopen(dev, "w")) == (FILE *) NULL)
bailout("can't open user's terminal", 5);
fprintf(fp,
"%s: You've been idle for %d min.\07\n", name, idle);
fprintf(fp,
"you'll be logged off in 60 sec. unless you hit return:");
fclose(fp);
fprintf(log, "** WARNING ** %s %s (%d min idle time) %s",
name, dev+5, idle, ctime(&tvec)+3);
}
if (flag == LOGOFF) { /* process log-off message */
fprintf(log, "** LOGOFF ** %s %s (%d min idle time) %s",
name, dev + 5, idle, ctime(&tvec) + 3);
sprintf(mbuf, "/bin/mail %s", name);
/* open pipe to mail program for writing */
if ((mprog = popen(mbuf, "w")) == (FILE *) NULL)
bailout("can't use /bin/mail program", 6);
fprintf(mprog, "Subject: Excess Idle Time\nLogged \
off - excess idle time - %s %s\ntty = %s\n",
name, ctime(&tvec), dev + 5);
fclose(mprog);
}
if (flag == NOLOGOFF) { /* send mail to root if can't kill */
fprintf(log, "** LOGOFF-FAIL ** %s (pid = %d) \
%s (%d min idle time) %s",
name, utmpp->ut_pid, dev+5, idle, ctime(&tvec)+3);
sprintf(mbuf, "/bin/mail root");
if ((mprog = popen(mbuf, "w")) == (FILE *) NULL)
bailout("can't use /bin/mail program", 7);
fprintf(mprog, "Subject: Can't logoff %s\nCan't Log off \
- %s %s\ntty = %s\n", name, name, ctime(&tvec), dev+5);
fclose(mprog);
}
fclose(log);
return(0);
}
killit(pid) /* terminate process using SIGHUP, then SIGKILL */
int pid;
{
kill(pid, SIGHUP); /* first send "hangup" signal */
sleep(KWAIT);
if (!kill(pid, 0)) { /* SIGHUP might be ignored */
kill(pid, SIGKILL); /* then send sure "kill" signal */
sleep(KWAIT);
if (!kill(pid, 0))
return(0); /* failure--refuses to die! */
else
return(1); /* successful kill with SIGKILL */
} else
return(1); /* successful kill with SIGHUP */
}
bailout(message, status) /* display error message and exit */
int status; /* exit status */
char *message; /* pointer to the error message */
{
fprintf(stderr, "autologout: %s\n", message);
exit(status);
}